﻿
//编译器类--把源程序编译为汇编程序
namespace n_SPCE061A_Assembler
{
using System;
using n_Compiler;
using n_ConstString;
using n_ET;
using n_spce061aLabel;
using i_Compiler;
using n_OS;

public static class SPCE061A_Assembler
{
	//编译器启动初始化,加载汇编运算库文件
	public static void LoadFile()
	{
		//加载运算信息表
		string s = i_Compiler.Compiler.OpenCompileFile( n_Config.Config.Path_compiler + "CPU" + OS.PATH_S + "SPCE061A" + OS.PATH_S + "hexcode.lst" );
		s = s.Remove( s.IndexOf( "\n<end>" ) );
		string[] Lines = s.Split( '\n' );
		HEXList = new string[ Lines.Length ][];
		for( int i = 0; i < Lines.Length; ++i ) {
			HEXList[ i ] = Lines[ i ].Remove( Lines[ i ].IndexOf( "<<<<" ) ).Split( '\\' );
		}
		//spce061a标号初始化
		spce061aLabel.Init();
	}
	
	//编译汇编文件
	public static string Assemble( string Source )
	{
		n_Compiler.Compiler.CompilingStep( n_Compiler.Compiler.STEP_InitAssemble );
		
		//清除标号列表
		spce061aLabel.Clear();
		Address = 0;
		
		n_Compiler.Compiler.CompilingStep( n_Compiler.Compiler.STEP_Assemble );
		
		//标准化,去除制表符等
		string[] Line = Standard( Source );
		
		//转换为机器码
		Source = TurnToCode( Line );
		
		ET.WriteLineError( 0, 0, "SPCE061A测试中" );
		return null;
	}
	
	//规范化,去除制表符等
	static string[] Standard( string Source )
	{
		Source = Source.ToLower();
		Source = Source.Replace( ",", " , " );
		Source = Source.Replace( ":", " : " );
		Source = Source.Replace( '\t', ' ' );
		string[] Line = Source.Split( '\n' );
		return Line;
	}
	
	//转换为机器码
	static string TurnToCode( string[] Line )
	{
		string Result = "";
		for( int i = 0; i < Line.Length; ++i ) {
			
			string line = Line[ i ];
			//去掉注释
			int noteIndex = line.IndexOf( "//" );
			if( noteIndex != -1 ) {
				line = line.Remove( noteIndex );
			}
			noteIndex = line.IndexOf( ";" );
			if( noteIndex != -1 ) {
				line = line.Remove( noteIndex );
			}
			line = line.Trim( ' ' );
			if( line == "" ) {
				continue;
			}
			//去掉多余的空格
			line = TrimMultSpace( line );
			
			//提取数字,替换为 $n, n = 0,1,2,3 ...
			line = GetNumberChar( line );
			
			//获取机器码,包含表达式
			//line = GetBINcode( line );
			
			if( line != null ) {
				Result += line + "\n";
			}
		}
		return Result;
	}
	
	//提取数字,替换为 $n, n = 0,1,2,3 ...
	//格式: 语句 + \ + 数字1 + \ + 数字2 + \ + ...
	//语句中对应的数字序列则替换为 ?n
	static string GetNumberChar( string line )
	{
		string sentence = "";
		string NumberSet = null;
		bool isFirstNumber = true;
		bool LastisNumber = false;
		int Index = 0;
		
		//判断标号
		if( line.EndsWith( ":" ) ) {
			string LabelName = line.Split( ' ' )[ 0 ];
			spce061aLabel.AddNode( LabelName, Address.ToString() );
			return null;
		}
		//判断地址定位指令
		if( line.StartsWith( ".org " ) ) {
			string Addr = line.Split( ' ' )[ 1 ];
			string type = null;
			Address = int.Parse( ConstString.GetValue( ref type, Addr, 0 ) );
			return null;
		}
		//判断数据定义
		if( line.StartsWith( ".dw " ) ) {
			return SwitchData( line );
		}
		//如果含有标签,处理标签
		string label = "";
		bool labelisExist = false;
		if( isLabelSentence( line ) ) {
			labelisExist = true;
			int i = line.LastIndexOf( ' ' );
			label = line.Remove( 0, i + 1 );
			line = line.Remove( i + 1 );
		}
		//处理数字序列
		for( int i = 0; i < line.Length; ++i ) {
			if( LastisNumber &&
			    ( line[ i ] == 'b' || line[ i ] == 'x' || line[ i ] == 'a' || line[ i ] == 'b' ||
			    line[ i ] == 'c' || line[ i ] == 'd' || line[ i ] == 'e' || line[ i ] == 'f' ) ) {
				NumberSet += line[ i ];
				LastisNumber = true;
				continue;
			}    
			if( line[ i ] < '0' || line[ i ] > '9' ) {
				sentence += line[ i ];
				isFirstNumber = true;
				LastisNumber = false;
				continue;
			}
			if( isFirstNumber ) {
				NumberSet += "\\";
				sentence += "?" + Index;
				++Index;
				isFirstNumber = false;
			}
			NumberSet += line[ i ];
			LastisNumber = true;
		}
		if( labelisExist ) {
			sentence += "?" + Index;
			NumberSet += "\\" + label;
		}
		return sentence + NumberSet;
	}
	
	//处理数据定义
	static string SwitchData( string line )
	{
		string Result = "";
		line = line.Remove( 0, 4 );
		string[] Word = line.Split( ',' );
		for( int i = 0; i < Word.Length; ++i ) {
			Result += ".dw " + Address + " (16:" + Word[ i ].Trim( ' ' ) + ")\n";
			Address += 1;
		}
		return Result.Trim( '\n' );
	}
	
	//判断是否包含标签
	static bool isLabelSentence( string line )
	{
		if( line.StartsWith( "goto " ) ||
		    line.StartsWith( "call " ) ||
		    line.StartsWith( "jb " ) ||
		    line.StartsWith( "jnae " ) ||
		    line.StartsWith( "jna " ) ||
		    line.StartsWith( "jbe " ) ||
		    line.StartsWith( "jnb " ) ||
		    line.StartsWith( "ja " ) ||
		    line.StartsWith( "jnbe " ) ||
		    line.StartsWith( "jae " ) ||
		    line.StartsWith( "jnge " ) ||
		    line.StartsWith( "jl " ) ||
		    line.StartsWith( "jng " ) ||
		    line.StartsWith( "jnl " ) ||
		    line.StartsWith( "jle " ) ||
		    line.StartsWith( "jnle " ) ||
		    line.StartsWith( "jg " ) ||
		    line.StartsWith( "jge " ) ||
		    line.StartsWith( "jvc " ) ||
		    line.StartsWith( "jvs " ) ||
		    line.StartsWith( "jcc " ) ||
		    line.StartsWith( "jcs " ) ||
		    line.StartsWith( "jsc " ) ||
		    line.StartsWith( "jss " ) ||
		    line.StartsWith( "jnz " ) ||
		    line.StartsWith( "jz " ) ||
		    line.StartsWith( "jmi " ) ||
		    line.StartsWith( "jpl " ) ||
		    line.StartsWith( "je " ) ||
		    line.StartsWith( "jne " ) ) {
			return true;
		}
		return false;
	}
	
	//去掉多余的空格
	static string TrimMultSpace( string line )
	{
		string r = "";
		bool ignore = true;
		for( int i = 0; i < line.Length; ++i ) {
			if( line[ i ] != ' ' ) {
				r += line[ i ];
				ignore = false;
				continue;
			}
			if( !ignore ) {
				r += " ";
				ignore = true;
			}
		}
		return r;
	}

	static string[][] HEXList;
	static int Address;
}
}

